package com.air.db;

import com.air.beans.SearchResult;
import com.air.listeners.StartSearchListener;
import com.air.tools.PropertiesTools;
import com.air.tools.StringTools;
import com.air.tools.TaskFather;
import com.air.tools.output;
import lombok.Data;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 表的数据库dao
 *
 * @author Air
 * @date 2018年11月21日15:03:39
 * @since v1
 */
@Data
public class TableDao {
    /**
     * 是否快速模式-精确到表，不精确到列
     */
    private boolean isFast;

    /**
     * 搜索所有的表,查询包含指定文本的表的字段
     *
     * @param text
     * @return
     */
    public List<SearchResult> queryTableAllColumn(String text) {
        if (StringTools.isEmptyWithTrimOrNull(text)) {
            return new ArrayList<>(0);
        }
        List<SearchResult> re = new ArrayList<>(tabs.size());
        Connection conn = DbConnectionFactory.getConnection();
        Statement st = null;
        ResultSet rs = null;
        ResultSet rsContent = null;
        try {
            st = conn.createStatement();
            SearchResult searchResult;
            ResultSetMetaData metaData;
            String sql_QueryTableColum = "select * from ";
            String sql_QueryContent = " from ";
            String whereNoResult = "1=2";
            String whereContent = "  like '%" + text + "%'";
            if (1 == PropertiesTools.getInstance().getLikeType()) {
                whereContent = "  like '" + text + "%'";
            }else if (2 == PropertiesTools.getInstance().getLikeType()) {
                whereContent = "  like '%" + text + "'";
            }

            whereContent = text.startsWith("where:") ?
                    text.replace("where:"
                            , StringTools.EMTPYSTRING) : whereContent;
            String where = " where ";
            String sql;
            ArrayList<String> columNames;
            for (String tab : tabs) {
                if (taskFather.isStop()) {
                    break;
                }
                rs = st.executeQuery(sql_QueryTableColum + tab
                        + where + whereNoResult);
                metaData = rs.getMetaData();
                int columCount = metaData.getColumnCount();
                columNames = new ArrayList<>(columCount);
                for (int columIndex = 1; columIndex <= columCount; columIndex++) {
                    if (!metaData.isSearchable(columIndex)
                        //    ||
                    ) {
                        //跳过 不能对比字符串的类型列
                        continue;
                    }
                    columNames.add(metaData.getColumnName(columIndex));
                }
                if (isFast()) {
                    System.out.println("快速模式搜索表: " + tab);

                    sql = sql_QueryContent + tab + where + " " + inSql(whereContent, columNames);
                    rsContent = st.executeQuery(appendLimitSql(sql));
                    if (rsContent.next()) {
                        searchResult = new SearchResult();
                        searchResult.setColumName("");
                        searchResult.setTableName(tab);
                        searchResult.setSql("select * " + sql);
                        re.add(searchResult);
                        taskFather.addSearchResult(searchResult);
                    }
                    rsContent.close();
                } else {
                    for (String columName : columNames) {
                        System.out.println("搜索表: " + tab + " 中列: " + columName);
                        sql = sql_QueryContent + tab + where
                                + columName + whereContent;
                        rsContent = st.executeQuery(appendLimitSql(sql));
                        if (rsContent.next()) {
                            searchResult = new SearchResult();
                            searchResult.setColumName(columName);
                            searchResult.setTableName(tab);
                            searchResult.setSql("select * " + sql);
                            re.add(searchResult);
                            taskFather.addSearchResult(searchResult);
                        }
                        rsContent.close();
                    }
                }
                rs.close();
            }
            st.close();
        } catch (SQLException e) {
            output.outLine(e.toString());
            e.printStackTrace();
            return re;
        } finally {
            try {
                if (null != rs) {
                    rs.close();
                }
                if (null != st) {
                    st.close();
                }
                if (null != rsContent) {
                    rsContent.close();
                }
            } catch (SQLException e) {
                output.outLine(e.toString());
                e.printStackTrace();
            }
        }
        return re;
    }

    private String appendLimitSql(String sql) {
        int dbType = PropertiesTools.getInstance().getDbType();

        switch (dbType) {
            case 0://oracle
                return "select * from ( select rownum,1 " + sql + " ) where rownum =1 ";
            case 1://sqlserver
                return "select top 1 'a' " + sql;
            case 2://mysql
                return "select 1 " + sql + " limit 1 ";
        }

        return sql;
    }

    private String inSql(String whereContent, ArrayList<String> columNames) {
        StringBuilder sb = new StringBuilder(1000);
        boolean first = true;

        for (String columName : columNames) {
            if (!first) {
                sb.append(" or ");
            } else {
                first = false;
            }

            sb.append(columName).append(whereContent);
        }

        return sb.toString();
    }

    /**
     * 是否不能 进行字符串对比
     *
     * @param columnTypeName
     * @return
     */
    private static boolean isSkipColumType(String columnTypeName) {
        if ("BLOB".equals(columnTypeName)) {
            //BLOB 类型要跳过
            return true;
        }
        return false;
    }


    public TableDao(TaskFather taskFather, StartSearchListener startSearchListener, List<String> tabs) {
        this.taskFather = taskFather;
        this.startSearchListener = startSearchListener;
        this.tabs = tabs;
    }

    private TaskFather taskFather;
    private StartSearchListener startSearchListener;
    private List<String> tabs;
}
